package com.cyou.weplay.redis;

import java.sql.Connection;
import java.sql.SQLException;

import javax.sql.DataSource;

import com.cyou.weplay.db.ShardedJdbcDataLayer;
import com.cyou.weplay.db.TableShardInfo;
import com.cyou.weplay.db.TableShardManager;
import com.cyou.weplay.utils.StringUtils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.datasource.DataSourceUtils;

/**
 * RedisDataLayer
 *
 * @author zhaomingyu
 * @param <T>
 * @param <E>
 */
public abstract class RedisDataLayer<T, E extends RedisEntity> extends ShardedJdbcDataLayer {

    private static final Logger logger = LoggerFactory.getLogger(RedisDataLayer.class);

    protected String tableName;

    public RedisDataLayer(TableShardManager tableShardManager) {
        super(tableShardManager);
    }

    public T getData(String id) throws Exception {
        T t = null;
        TableShardInfo shardInfo = this.shardManager.getShardInfo(tableName, id);
        DataSource datasource = shardInfo.getDatasource();
        Connection connection = DataSourceUtils.getConnection(datasource);
        try {
            String shardedName;
            if(StringUtils.isEmpty(shardInfo.getShardedName())) {
                shardedName = tableName;
            } else {
                shardedName = shardInfo.getShardedName();
            }
            t = getData(shardedName, id, connection);
        } catch (SQLException ex) {
            throw ex;
        } finally {
            DataSourceUtils.releaseConnection(connection, datasource);
        }
        return t;
    }

    protected abstract T getData(String tableName, String id, Connection conn) throws SQLException;

    public void saveData(E e) throws Exception {
        TableShardInfo shardInfo = this.shardManager.getShardInfo(tableName, e.entityId);
        DataSource datasource = shardInfo.getDatasource();
        Connection connection = DataSourceUtils.getConnection(datasource);
        try {
            String shardedName;
            if(StringUtils.isEmpty(shardInfo.getShardedName())) {
                shardedName = tableName;
            } else {
                shardedName = shardInfo.getShardedName();
            }
            saveData(shardedName, e, connection);
        } catch (SQLException ex) {
            throw ex;
        } finally {
            DataSourceUtils.releaseConnection(connection, datasource);
        }
    }

    protected abstract void saveData(String tableName, E e, Connection conn) throws SQLException;

}
